//-----------------------------------------------------------------------------
//           Name: ogl_multiple_vertex_arrays.cpp
//         Author: Kevin Harris
//  Last Modified: 02/01/05
//    Description: This sample demonstrates how to create 3D geometry with 
//                 OpenGL by loading vertex data into a multiple Vertex 
//                 Arrays.
//-----------------------------------------------------------------------------
#define win_size_w 1000
#define win_size_h 1000
#include "header.h"
#include "ThreeMaxLoader.h"

obj_type object_ds;

//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HWND   g_hWnd = NULL;
HDC	   g_hDC = NULL;
HGLRC  g_hRC = NULL;
GLuint g_textureID = -1;

float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
int ins = 0;

POINT dot[4][1000];
POINT MAX = { 0, 0 };
POINT nMAX;
POINT MIN = { 9999, 9999 };
POINT nMIN;

int t_left;
int t_top;
int t_right;
int t_bottom;

POINT nDT[5000];


typedef struct {
	int r;
	int g;
	int b;
}ctype;
ctype cT[4][1000];
int nDot[4] = { 0, 0, 0, 0 }, nDCT = 0;

struct Vertex
{
	float x, y, z;
};
Vertex g_cubeVertices[] =
{
	{ -1.0f, -1.0f, 1.0f },
	{ 1.0f, -1.0f, 1.0f },
	{ 1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f },

	{ -1.0f, -1.0f, -1.0f },
	{ -1.0f, 1.0f, -1.0f },
	{ 1.0f, 1.0f, -1.0f },
	{ 1.0f, -1.0f, -1.0f },

	{ -1.0f, 1.0f, -1.0f },
	{ -1.0f, 1.0f, 1.0f },
	{ 1.0f, 1.0f, 1.0f },
	{ 1.0f, 1.0f, -1.0f },

	{ -1.0f, -1.0f, -1.0f },
	{ 1.0f, -1.0f, -1.0f },
	{ 1.0f, -1.0f, 1.0f },
	{ -1.0f, -1.0f, 1.0f },

	{ 1.0f, -1.0f, -1.0f },
	{ 1.0f, 1.0f, -1.0f },
	{ 1.0f, 1.0f, 1.0f },
	{ 1.0f, -1.0f, 1.0f },

	{ -1.0f, -1.0f, -1.0f },
	{ -1.0f, -1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, -1.0f }
};
struct Color
{
	float r, g, b;
};
Color g_cubeColors[] =
{
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },

	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },

	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },

	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },

	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },

	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f }
};
struct TexCoord
{
	float tu, tv;
};
TexCoord g_cubeTexCoords[] =
{
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },

	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },

	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },

	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },

	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },

	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f }
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND g_hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void loadTexture(void);
void initMain(void);
void renderMain(void);
void shutDown(void);

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX winClass;
	MSG        uMsg;

	memset(&uMsg, 0, sizeof(uMsg));

	winClass.lpszClassName = "MY_WINDOWS_CLASS";
	winClass.cbSize = sizeof(WNDCLASSEX);
	winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	winClass.lpfnWndProc = WindowProc;
	winClass.hInstance = hInstance;
	winClass.hIcon = NULL;// LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);
	winClass.hIconSm = NULL;// LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);
	winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	winClass.lpszMenuName = NULL;
	winClass.cbClsExtra = 0;
	winClass.cbWndExtra = 0;

	if (!RegisterClassEx(&winClass))
		return E_FAIL;

	g_hWnd = CreateWindowEx(NULL, "MY_WINDOWS_CLASS",
		"OpenGL - Multiple Vertex Arrays",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		0, 0, win_size_w, win_size_h, NULL, NULL, hInstance, NULL);

	if (g_hWnd == NULL)
		return E_FAIL;

	ShowWindow(g_hWnd, nCmdShow);
	SetWindowLong(g_hWnd, GWL_EXSTYLE, GetWindowLong(g_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
	UpdateWindow(g_hWnd);

	initMain();

	renderMain();
	while (uMsg.message != WM_QUIT)
	{
		if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&uMsg);
			DispatchMessage(&uMsg);
		}
		else
			renderMain();
	}

	shutDown();

	UnregisterClass("MY_WINDOWS_CLASS", winClass.hInstance);

	return uMsg.wParam;
}

//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND   g_hWnd, UINT   msg, WPARAM wParam, LPARAM lParam)
{
	static POINT ptLastMousePosit;
	static POINT ptCurrentMousePosit;
	static bool bMousing;

	switch (msg)
	{
	case WM_KEYDOWN:
	{
		switch (wParam)
		{
		case VK_ESCAPE:
			PostQuitMessage(0);
			break;
		}
	}
	break;

	case WM_LBUTTONDOWN:
	{
		ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD(lParam);
		ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD(lParam);
		bMousing = true;
	}
	break;

	case WM_LBUTTONUP:
	{
		bMousing = false;
	}
	break;

	case WM_MOUSEMOVE:
	{
		ptCurrentMousePosit.x = LOWORD(lParam);
		ptCurrentMousePosit.y = HIWORD(lParam);

		if (bMousing)
		{
			g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
			g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
		}
		ptLastMousePosit.x = ptCurrentMousePosit.x;
		ptLastMousePosit.y = ptCurrentMousePosit.y;
	}
	break;

	case WM_SIZE:
	{
		int nWidth = LOWORD(lParam);
		int nHeight = HIWORD(lParam);
		glViewport(500, 500, nWidth, nHeight);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0, (GLdouble)nWidth / (GLdouble)nHeight, 0.1, 100.0);
	}
	break;
	case WM_CLOSE:
	{
		PostQuitMessage(0);
	}

	case WM_DESTROY:
	{
		PostQuitMessage(0);
	}
	break;

	default:
	{
		return DefWindowProc(g_hWnd, msg, wParam, lParam);
	}
	break;
	}

	return 0;
}

//-----------------------------------------------------------------------------
// Name: loadTexture()
// Desc: 
//-----------------------------------------------------------------------------
void loadTexture(void)
{
	AUX_RGBImageRec *pTextureImage = auxDIBImageLoad(".\\test.bmp");

	if (pTextureImage != NULL)
	{
		glGenTextures(1, &g_textureID);

		glBindTexture(GL_TEXTURE_2D, g_textureID);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

		glTexImage2D(GL_TEXTURE_2D, 0, 3, pTextureImage->sizeX, pTextureImage->sizeY, 0,
			GL_RGB, GL_UNSIGNED_BYTE, pTextureImage->data);
	}

	if (pTextureImage != NULL)
	{
		if (pTextureImage->data != NULL)
			free(pTextureImage->data);

		free(pTextureImage);
	}
}

void initMain(void)
{
	GLuint PixelFormat;

	PIXELFORMATDESCRIPTOR pfd;
	memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 16;
	pfd.cDepthBits = 16;

	g_hDC = GetDC(g_hWnd);
	PixelFormat = ChoosePixelFormat(g_hDC, &pfd);
	SetPixelFormat(g_hDC, PixelFormat, &pfd);
	g_hRC = wglCreateContext(g_hDC);
	wglMakeCurrent(g_hDC, g_hRC);

	loadTexture();

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, 640.0f / 480.0f, 10.0f, 100.0f);


	glClearColor(1.0, 0.0, 1.0, 1);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity(); 
	gluPerspective(45.0f, (GLfloat)win_size_w / (GLfloat)win_size_h, 10.0f, 1000.0f);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	//Convert string to char

	CThreeMaxLoader::Load3DS(&object_ds, "132.3ds");
}

void shutDown(void)
{
	glDeleteTextures(1, &g_textureID);

	if (g_hRC != NULL)
	{
		wglMakeCurrent(NULL, NULL);
		wglDeleteContext(g_hRC);
		g_hRC = NULL;
	}

	if (g_hDC != NULL)
	{
		ReleaseDC(g_hWnd, g_hDC);
		g_hDC = NULL;
	}
}
int chkCNT(int x, int y)
{
	int i;
	for (i = nDCT - 1; i >0; i--)
	{
		if (x == nDT[i].x && y == nDT[i].y)
			return 1;
	}
	return 0;
}
void renderMain(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0f, 0.0f, -10.0f);
	glRotatef(-g_fSpinY, 1.0f, 0.0f, 0.0f);
	glRotatef(-g_fSpinX, 0.0f, 1.0f, 0.0f);

	{
		int l_index;
		glBegin(GL_TRIANGLES);
		for (l_index = 0; l_index<object_ds.polygons_qty; l_index++)
		{
			//----------------- FIRST VERTEX -----------------
			// Coordinates of the first vertex
			glVertex3f(object_ds.vertex[object_ds.polygon[l_index].a].x,
				object_ds.vertex[object_ds.polygon[l_index].a].y,
				object_ds.vertex[object_ds.polygon[l_index].a].z); //Vertex definition

			//----------------- SECOND VERTEX -----------------
			// Coordinates of the second vertex

			glVertex3f(object_ds.vertex[object_ds.polygon[l_index].b].x,
				object_ds.vertex[object_ds.polygon[l_index].b].y,
				object_ds.vertex[object_ds.polygon[l_index].b].z);

			//----------------- THIRD VERTEX -----------------
			// Coordinates of the Third vertex
			glVertex3f(object_ds.vertex[object_ds.polygon[l_index].c].x,
				object_ds.vertex[object_ds.polygon[l_index].c].y,
				object_ds.vertex[object_ds.polygon[l_index].c].z);
		}
		glEnd();
		//glutSwapBuffers();
	}


	//glBindTexture(GL_TEXTURE_2D, g_textureID);
	
	//glEnableClientState(GL_VERTEX_ARRAY);
	//glEnableClientState(GL_COLOR_ARRAY);
	//glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	//glVertexPointer(3, GL_FLOAT, 0, g_cubeVertices);
	//glColorPointer(3, GL_FLOAT, 0, g_cubeColors);
	//glTexCoordPointer(2, GL_FLOAT, 0, g_cubeTexCoords);

	//glDrawArrays(GL_QUADS, 0, 24);
	
	//glDisableClientState(GL_VERTEX_ARRAY);
	//glDisableClientState(GL_COLOR_ARRAY);
	//glDisableClientState(GL_TEXTURE_COORD_ARRAY); 


	/*{
		BYTE *iData = (BYTE*)malloc((win_size_w)* (win_size_h)* 3);
		glReadPixels(0, 0, win_size_w, win_size_h, GL_RGB, GL_UNSIGNED_BYTE, iData);
		int x, y;
		int dx[8] = { -1,-1,0,1,1,1,0,-1};
		int dy[8] = { 0,1,1,1,0,-1,-1,-1 };
		nDCT = 0;
		for (int i = 0; i < win_size_w - 16; i++)
		{
			for (int j = 39; j < win_size_h ; j++)
			{
				int t = ((win_size_h - j - 1) * win_size_w + i) * 3;
				if (!(iData[t + 0] == 255 && iData[t + 1] == 0 && iData[t + 2] == 255))
				{
					nDT[nDCT].x = x = i;
					nDT[nDCT].y = y = j;
					nDCT++;
					break;
				}
			}
			if (nDCT) break;
		}

	}*/

	BYTE *iData = (BYTE*)malloc((win_size_w)* (win_size_h)* 3);
	glReadPixels(0, 0, win_size_w, win_size_h, GL_RGB, GL_UNSIGNED_BYTE, iData);
	int dx[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
	int dy[] = { 1, 1, 0, -1, -1, -1, 0, 1 };
	int  temp = 0;
	nDot[0] = 0;
	nDot[1] = 0;
	nDot[2] = 0;
	nDot[3] = 0;
	t_top = 0;
	t_left = 0;
	t_right = 0;
	t_bottom = 0;
	MIN = { 999, 999 };
	MAX = { 0, 0 };
	nMIN = { 0, 0 };
	nMAX = { 0, 0 };
	for (int j = 39; j < win_size_h; j++)
	{
		for (int i = 0; i < win_size_w - 16; i++)
		{
			int t = ((win_size_h - j - 1) * win_size_w + i) * 3;
			if (!(iData[t + 0] == 255 && iData[t + 1] == 0 && iData[t + 2] == 255))
			{
				if (i < MIN.x)
				{
					MIN.x = i;
					nMIN.x = nDot[0];
				}
				if (nMIN.x != 0 && i > MIN.x)
					t_left = nDot[0];
				dot[0][nDot[0]].x = i;
				cT[0][nDot[0]].r = iData[t];
				cT[0][nDot[0]].g = iData[t + 1];
				cT[0][nDot[0]].b = iData[t + 2];
				dot[0][nDot[0]++].y = j;
				temp = i;
				break;
			}
		}
		for (int i = win_size_w - 17; i > temp; i--)
		{
			int t = ((win_size_h - j - 1) * win_size_w + i) * 3;
			if (!(iData[t + 0] == 255 && iData[t + 1] == 0 && iData[t + 2] == 255))
			{
				if (i >= MAX.x)
				{
					MAX.x = i;
					nMAX.x = nDot[1];
				}
				if (nMAX.x != 0 && i < MAX.x)
					t_right = nDot[1];
				dot[1][nDot[1]].x = i;
				cT[1][nDot[1]].r = iData[t];
				cT[1][nDot[1]].g = iData[t + 1];
				cT[1][nDot[1]].b = iData[t + 2];
				dot[1][nDot[1]++].y = j;
				break;
			}
		}
	}

	for (int i = 0; i < win_size_w - 16; i++)
	{
		for (int j = 39; j < win_size_h; j++)
		{
			int t = ((win_size_h - j - 1) * win_size_w + i) * 3;
			if (!(iData[t + 0] == 255 && iData[t + 1] == 0 && iData[t + 2] == 255))
			{
				if (j < MIN.y)
				{
					MIN.y = j;
					nMIN.y = nDot[2];
				}
				if (nMIN.y != 0 && j > MIN.y)
					t_top = nDot[2];
				dot[2][nDot[2]].x = i;
				cT[2][nDot[2]].r = iData[t];
				cT[2][nDot[2]].g = iData[t + 1];
				cT[2][nDot[2]].b = iData[t + 2];
				dot[2][nDot[2]++].y = j;
				temp = j;
				break;
			}
		}
		for (int j = win_size_h - 1; j >temp; j--)
		{
			int t = ((win_size_h - j - 1) * win_size_w + i) * 3;
			if (!(iData[t + 0] == 255 && iData[t + 1] == 0 && iData[t + 2] == 255))
			{
				if (j > MAX.y)
				{
					MAX.y = j;
					nMAX.y = nDot[3];
				}
				if (nMAX.y != 0 && j < MAX.y)
					t_bottom = nDot[3];
				dot[3][nDot[3]].x = i;
				cT[3][nDot[3]].r = iData[t];
				cT[3][nDot[3]].g = iData[t + 1];
				cT[3][nDot[3]].b = iData[t + 2];
				dot[3][nDot[3]++].y = j;
				break;
			}
		}
	}
	free(iData);

	nDCT = 0;
	for (int i = t_top; dot[2][i].x > dot[0][t_left].x; i--)
	{
		nDT[nDCT].x = dot[2][i].x + 8;
		nDT[nDCT++].y = dot[2][i].y - 7;
	}
	for (int i = t_left; dot[0][i].y < dot[3][t_bottom].y; i++)
	{
		nDT[nDCT].x = dot[0][i].x + 9;
		nDT[nDCT++].y = dot[0][i].y - 8;
	}
	for (int i = t_bottom; dot[3][i].x < dot[1][t_right].x; i++)
	{
		nDT[nDCT].x = dot[3][i].x + 8;
		nDT[nDCT++].y = dot[3][i].y - 8;
	}
	for (int i = t_right; dot[1][i].y > dot[2][t_top].y; i--)
	{
		nDT[nDCT].x = dot[1][i].x + 7;
		nDT[nDCT++].y = dot[1][i].y - 8;
	}
	
	/*FILE *fp = fopen("out.txt", "w");
	fprintf(fp, "%d\n", nDCT);
	for (int i = 0; i < nDCT; i++)
	fprintf(fp, "x : %d , y : %d , R : %d\tG : %d\tB : %d\n", nDT[i].x , nDT[i].y,0,0,0);
	fclose(fp);*/
	SetWindowRgn(g_hWnd, CreatePolygonRgn(nDT, nDCT - 1, 1), TRUE);

	SwapBuffers(g_hDC);
	SetLayeredWindowAttributes(g_hWnd, RGB(255, 0, 255), 255, LWA_ALPHA | LWA_COLORKEY);
	UpdateWindow(g_hWnd);
}
